#!/bin/bash

NOFEVENTS="100"
NOFSIMULS="1"
TRANSPORTNAME="TGeant3"
TRANSPORT="--transport zeromq"
WORKDIR="@PIXEL_FILE_LOCATION@"
SEVERITY="--severity info"
VERBOSITY="--verbosity medium"
COLOR="--color true"
FORCEKILL=false
COMMAND="interactive"
FAIRROOTCONFIGDIR=""
MAXRUNNINGTIME=100

DATESTRING=`date +%Y%m%d_%H%M%S`

NOFRANDOMNUMBERS=0

while [[ $# > 1 ]]
do
key="$1"

case $key in
    -n|--nof-events)
    NOFEVENTS="$2"
    shift
    ;;
    -r|--random-number)
    RANDOMNUMBER[NOFRANDOMNUMBERS]="$2"
    NOFRANDOMNUMBERS=$((NOFRANDOMNUMBERS + 1))
    shift
    ;;
    -s|--nof-simuls)
    NOFSIMULS="$2"
    shift
    ;;
    -g|--transport-name)
    TRANSPORTNAME="$2"
    shift
    ;;
    -f|--fairroot-config-dir)
    FAIRROOTCONFIGDIR="--fairroot-config-dir $2"
    shift
    ;;
    -t|--transport)
    TRANSPORT="--transport $2"
    shift
    ;;
    -w|--work-dir)
    WORKDIR="$2"
    shift
    ;;
    -c|--command)
    COMMAND="$2"
    shift
    ;;
    -m|--max-running-time)
    MAXRUNNINGTIME="$2"
    shift
    ;;
    -y|--severity)
    SEVERITY="--severity $2"
    shift
    ;;
    -v|--verbosity)
    VERBOSITY="--verbosity $2"
    shift
    ;;
    -l|--color)
    COLOR="--color $2"
    shift
    ;;
    -k|--force-kill)
    FORCEKILL="$2"
    shift
    ;;
esac
shift 
done

CONTROL=""
if [ "$COMMAND" == "static" ]; then
    CONTROL="--control static --log-color false"
fi

case $NOFSIMULS in
    ''|*[!0-9]*) NOFSIMULS=1 ;;
    *) ;;
esac

unameOut=$(uname -s)
case $unameOut in
    Linux)     NOFCORES=$(cat /proc/cpuinfo | grep processor | wc -l);;
    Darwin)    NOFCORES=$(sysctl -n hw.ncpu);;
    *)         NOFCORES=1;;
esac

if (( $NOFSIMULS == 0 )); then
    NOFSIMULS=1
fi
if (( $NOFSIMULS > $NOFCORES )); then
    echo "$NOFCORES cores detected. Reducing number of parallel samplers to $NOFCORES"
    NOFSIMULS=$NOFCORES
fi

if [ "$TRANSPORTNAME" != "TGeant4" ]; then
    TRANSPORTNAME="TGeant3"
fi

if (( $NOFRANDOMNUMBERS > 0 )); then
    if (( $NOFRANDOMNUMBERS < $NOFSIMULS )); then
        echo "The number of random seed set is smaller than the number of parallel simulation!"
    fi
fi

CHECK_BEFORE="$(ps -fea | grep "channel-config" | grep "transport" | grep "control" | grep -v grep)"
if [ -n "$CHECK_BEFORE" ];
then
    echo "some example/MQ/pixel programs are still running:"
    echo $CHECK_BEFORE
    echo "quit them before proceeding."
    if [ "$FORCEKILL" == "true" ];
    then
        echo "trying to kill..."
        ps -fea | grep "channel-config" | grep "transport" | grep "control" | grep -v grep | awk '{print $2}' | xargs kill -9
    else
        return;
    fi
fi

########################### Define some variables
# ASCII and ROOT parameter files for the processor device
OUTPUTPARAM="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.simulation_$TRANSPORTNAME.pars.root"
OUTPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.simulation_$TRANSPORTNAME.data.root"
###########################

TRANSPORTNAME="--transport-name $TRANSPORTNAME"

########################### Check if files exist
if [ ! -e $MQCONFIGFILE ] ; then
    echo "MQConfig file ($MQCONFIGFILE) does not exist!"
    exit;
fi

########################### Start the chain of the devices


########################## start Parameter server
SERVER="@FAIRROOT_BIN_LOCATION@/"
SERVER+="parmq-server $TRANSPORT"
SERVER+=" --id pixSim-parmq-server  --channel-config name=updateChannel,type=rep,method=bind,rateLogging=1,address=tcp://*:5205"
SERVER+=" $SEVERITY "
SERVER+=" $VERBOSITY "
SERVER+=" $COLOR "
SERVER+=" --update-channel-name updateChannel --output-name $OUTPUTPARAM $CONTROL"

########################## start SAMPLER
SAMPLER="@PIXEL_BIN_LOCATION@/"
SAMPLER+="run-sim $TRANSPORT"
SAMPLER+=" --channel-config name=updateChannel,type=req,method=connect,rateLogging=1,address=tcp://localhost:5205"
SAMPLER+=" --channel-config name=data#all#,type=push,method=connect,rateLogging=1,address=tcp://localhost:5206"
SAMPLER+=" $SEVERITY "
SAMPLER+=" $VERBOSITY "
SAMPLER+=" $COLOR "
SAMPLER+=" --nof-events $NOFEVENTS $TRANSPORTNAME $FAIRROOTCONFIGDIR $CONTROL"

for (( i=$NOFRANDOMNUMBERS ; i<$NOFSIMULS ; i++ ))
do
    RANDOMNUMBER[i]=0
done

for (( i=0 ; i<$NOFSIMULS ; i++ ))
do
    ASAMPLER[i]="$SAMPLER --id pixSim-sampler$i --random-seed ${RANDOMNUMBER[i]}"
done
########################## start FILESINK
FILESINK="@PIXEL_BIN_LOCATION@/"
FILESINK+="pixel-sink $TRANSPORT --in-channel data#all#"
FILESINK+=" $SEVERITY "
FILESINK+=" $VERBOSITY "
FILESINK+=" $COLOR "
FILESINK+=" --id pixSim-sink1 --channel-config name=data#all#,type=pull,method=bind,rateLogging=1,address=tcp://*:5206"
FILESINK+=" --class-name FairMCEventHeader --branch-name MCEventHeader."
FILESINK+=" --class-name TClonesArray(PixelPoint) --branch-name PixelPoint"
FILESINK+=" --class-name TClonesArray(FairMCTrack) --branch-name MCTrack"
FILESINK+=" --file-name $OUTPUTFILE $CONTROL"

########################## run all
if [ "$COMMAND" == "print" ]; then
    echo $SERVER
    echo $FILESINK

    for (( i=0 ; i<$NOFSIMULS ; i++ ))
    do
	echo ${ASAMPLER[i]}
    done
fi

if [ "$COMMAND" == "interactive" ]; then
    xterm -geometry 80x50+0+0 -hold -e $SERVER &
    xterm -geometry 80x50+1000+0 -hold -e $FILESINK &

    for (( i=0 ; i<$NOFSIMULS ; i++ ))
    do
	xterm -geometry 80x50+500+0 -hold -e ${ASAMPLER[i]} &
    done
fi

if [ "$COMMAND" == "static" ]; then
    CHECK_BEFORE="$(ps -fea | grep pixSim | grep -v grep)"
    if [ -n "$CHECK_BEFORE" ];
    then
	echo "some example/MQ/pixel programs are still running:"
	echo $CHECK_BEFORE
	echo "quit them before proceeding."
	if [ "$FORCEKILL" == "true" ];
	then
            echo "trying to kill..."
            ps -fea | grep pixSim | grep -v grep | awk '{print $2}' | xargs kill -9
	else
            exit
	fi
    fi

    $SERVER &> server_$DATESTRING.out.log &
    SERVER_PID=$!

    for (( i=0 ; i<$NOFSIMULS ; i++ ))
    do
	${ASAMPLER[i]} &> sampler${i}_$DATESTRING.out.log &
	SAMPLER_PID[i]=$!
    done

    $FILESINK &> fileSink_$DATESTRING.out.log &
    FILESINK_PID=$!

    RUN_STRING="Running"

    for (( isimul=0 ; isimul<$NOFSIMULS+2 ; isimul++ ))
    do
	printf "_______________"
    done
    printf "_\n|     server   |"
    for (( isimul=0 ; isimul<$NOFSIMULS ; isimul++ ))
    do
	printf "    sampler   |"
    done
    printf "   file sink  |\n| pid = %6d |" $SERVER_PID
    for (( isimul=0 ; isimul<$NOFSIMULS ; isimul++ ))
    do
	printf " pid = %6d |" ${SAMPLER_PID[isimul]}
    done
    printf " pid = %6d |\n" $FILESINK_PID
    for (( isimul=0 ; isimul<$NOFSIMULS+2 ; isimul++ ))
    do
	printf "|   CPU    mem ";
    done
    printf "|\n"

    SAMPLERRUNNING=0
    for ((isec = 0 ; isec < MAXRUNNINGTIME ; isec++ ));
    do
	if (( SAMPLERRUNNING != -1 )); then
	    SAMPLERRUNNING=0
	    for (( isimul=0 ; isimul<$NOFSIMULS ; isimul++ ))
	    do
		CHECK_SAMPLER="$(kill -0 ${SAMPLER_PID[isimul]} &> /dev/null && echo $RUN_STRING)";
		if [ "$CHECK_SAMPLER" == "$RUN_STRING" ];
		then
		    SAMPLERRUNNING=1;
		fi
	    done
	    if (( SAMPLERRUNNING == 0 )); then
		MAXRUNNINGTIME=$((isec+2)); #TODO let it run for two more seconds after all samplers finish working... workaround for now
		SAMPLERRUNNING=-1
	    fi
	fi

	SERVER_INFO="$(ps -o %cpu -o rss $SERVER_PID | tail -1)"
	printf "| %5s %6s |" $SERVER_INFO;
	for (( isimul=0 ; isimul<$NOFSIMULS ; isimul++ ))
	do
	    SAMPLER_INFO="$(ps -o %cpu -o rss ${SAMPLER_PID[isimul]} | tail -1)"
	    printf " %5s %6s |" $SAMPLER_INFO;
	done
	FILESINK_INFO="$(ps -o %cpu -o rss $FILESINK_PID | tail -1)"
	printf " %5s %6s |\r" $FILESINK_INFO
	sleep 1;
    done;
    echo;
    for (( isimul=0 ; isimul<$NOFSIMULS+2 ; isimul++ ))
    do
	printf "_______________"
    done
    printf "_\n"
    echo "Jobs finished in $isec seconds."

    sleep 2;

    kill $SERVER_PID
    for (( i=0 ; i<$NOFSIMULS ; i++ ))
    do
	CHECK_SAMPLER="$(kill -0 ${SAMPLER_PID[isimul]} &> /dev/null && echo $RUN_STRING)";
	if [ "$CHECK_SAMPLER" == "$RUN_STRING" ];
	then
	    kill ${SAMPLER_PID[i]};
	fi
    done
    kill $FILESINK_PID

    wait $FILESINK_PID

    OUTPUT_EVENTS="$(echo "cout<<cbmsim->GetEntries()<<endl;" | root -l -b $OUTPUTFILE | tail -1)"
    echo "There are $OUTPUT_EVENTS events in the output file."

    if (( $OUTPUT_EVENTS == $NOFSIMULS*$NOFEVENTS ));
    then
	echo "Shell script finished successfully.";
    else
	echo " **** SAMP **** SAMP **** SAMP **** SAMP **** SAMP **** SAMP ****"
	cat sampler0_$DATESTRING.out.log
	echo " **** SERV **** SERV **** SERV **** SERV **** SERV **** SERV ****"
	cat server_$DATESTRING.out.log
	echo " **** SINK **** SINK **** SINK **** SINK **** SINK **** SINK ****"
	cat fileSink_$DATESTRING.out.log
	echo " **** **** **** **** **** **** **** **** **** **** **** **** ****"
    fi

fi


